package com.kalvan.admin.excel;

import cn.hutool.core.convert.Convert;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.kalvan.admin.annotation.Dict;
import com.kalvan.admin.annotation.ExtSuffix;
import com.kalvan.admin.annotation.NumberConvert;
import com.kalvan.admin.dict.CacheUtil;
import com.kalvan.sensitive.annotation.Desensitized;
import com.kalvan.sensitive.utils.SensitiveInfoUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author chenliang
 */
@Slf4j
public class CustomCellWriteHandler implements CellWriteHandler {

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        if (isHead && cell.getColumnIndex() == 0) {
            Field[] fields = writeSheetHolder.getClazz().getDeclaredFields();
            initAnnotation(fields);
        }
        if (!isHead) {
            convertValue(head.getFieldName(), cell);
        }
    }

    Map<String, Dict> dictField = new HashMap();
    Map<String, NumberConvert> numberConvertField = new HashMap();
    Map<String, ExtSuffix> extSuffixField = new HashMap<>();
    Map<String, Desensitized> desensitizedField = new HashMap<>();

    /**
     * 增加导出数据的转换
     *
     * @param fields fields
     */
    public void initAnnotation(Field[] fields) {
        // by kalvan 增加导出数据的转换
        for (Field field : fields) {
            if (field.getAnnotation(ExcelProperty.class) == null) {
                // throw new RuntimeException("@ExtExcel 只能用在@Excel字段上");
                continue;
            }
            // 字典转换
            if (field.getAnnotation(Dict.class) != null) {
                dictField.put(field.getName(), field.getAnnotation(Dict.class));
            }
            // 数字转换
            if (field.getAnnotation(NumberConvert.class) != null) {
                numberConvertField.put(field.getName(), field.getAnnotation(NumberConvert.class));
            }
            // 拼接内容
            if (field.getAnnotation(ExtSuffix.class) != null) {
                extSuffixField.put(field.getName(), field.getAnnotation(ExtSuffix.class));
            }
            // 脱敏导出
            if (field.getAnnotation(Desensitized.class) != null) {
                desensitizedField.put(field.getName(), field.getAnnotation(Desensitized.class));
            }
        }
    }

    /**
     * 根据列名和注解匹配转换
     * @param fieldName fieldName
     * @param cell cell
     */
    protected void convertValue(String fieldName, Cell cell) {
        String originValue = cell.toString();
        String newValue = null;
        Dict dict = dictField.get(fieldName);
        NumberConvert numberConvert = numberConvertField.get(fieldName);
        ExtSuffix extSuffix = extSuffixField.get(fieldName);
        Desensitized desensitized = desensitizedField.get(fieldName);
        if (dict != null) {
            newValue = CacheUtil.cache.getDictMap(dict.value()).get(originValue + "").getDictValue();
            if (StringUtils.isBlank(newValue) && originValue != null
                    && StringUtils.isNotBlank(originValue + "")) {
                // 没有转换则显示原值
                newValue = originValue;
            }
        }
        if (numberConvert != null) {
            Double number = Convert.toDouble(originValue);
            String precisionBit = StringUtils.rightPad("0.", numberConvert.precisionBit() + 2, "#");
            DecimalFormat decimalFormat = new DecimalFormat(precisionBit);
            newValue = decimalFormat.format(number / numberConvert.value());
        }
        if (extSuffix != null) {
            newValue = originValue + extSuffix.value();
        }
        if (desensitized != null) {
            newValue = SensitiveInfoUtils.convertMsg(desensitized.type(), originValue + "");
        }
        if (StringUtils.isNotBlank(newValue)) {
            //有匹配到转换则更新值
            cell.setCellValue(newValue);
        }
    }
}